package com.zhike.utils.push.ios;

import org.springframework.stereotype.Component;

import com.eva.epc.common.util.CommonUtils;
import com.zhike.common.dto.GroupInfo4Cache;
import com.zhike.common.dto.MsgBodyRoot;
import com.zhike.common.vo.UserInfo4Cache;
import com.zhike.utils.cache.GroupsInfoCacheProvider;
import com.zhike.utils.cache.UsersInfoCacheProvider;
import javax.annotation.Resource;

import lombok.extern.slf4j.Slf4j;

/**
 * 用于向iOS的设备进行离线消推送的辅助类。
 * 
 * @author Jack Jiang
 * @version 4.3
 */
@Slf4j
@Component
public class APNSPushHelper {
	@Resource
	private UsersInfoCacheProvider usersInfoCacheProvider;

	/**
	 * 尝试向已保存iOS设备token信息的用户进行聊天消息（包括群聊、陌生一对一、好友一对一聊）的APNs消息推送。
	 * 如果缓存中不存在该用户的ios设备token信息，则不需要推送。
	 * 
	 * @param chatType 聊天类型，@see {@link MsgBodyRoot}
	 * @param msgType  消息类型，@see {@link MsgBodyRoot}
	 * @param content  消息内容
	 * @param fromUid  消息发起人
	 * @param toUid    消息接收人
	 * @param toGid    消息发生的群（如果是群聊消息的话）
	 */
	public void tryPushChattingMessage(int chatType, int msgType, String content, String fromUid, String toUid,
			String toGid) {
		try {
			if (content == null || fromUid == null || toUid == null) {
				throw new IllegalArgumentException(
						"无效的参数content=" + content + ", fromUid=" + fromUid + ", toUid=" + toUid + "!");
			}

			// ## 尝试向ios设备进行APNs离线消息推送
			UserInfo4Cache iosTokenInfo = usersInfoCacheProvider.get(toUid);
			// 用户的Ios 设备token不为空才需要推送
			if (iosTokenInfo != null && !CommonUtils.isStringEmpty(iosTokenInfo.getIosDeviceToken())) {
				String pushContent = null;

				// 如果是群聊
				if (chatType == MsgBodyRoot.CHAT_TYPE_GROUP$CHAT) {
					GroupInfo4Cache g = GroupsInfoCacheProvider.getInstance().get(toGid);

					if (g != null) {
						// 这是群聊的系统通知
						if (msgType == MsgBodyRoot.TYPE_SYSTEAM$INFO) {
							pushContent = g.getGname() + ":" + content;
						}
						// 这是普通的聊群消息
						else {
							UserInfo4Cache u = usersInfoCacheProvider.get(fromUid);
							if (u != null) {
								String gname = g.getGname();
								String fromNickname = u.getNickName();

								// 形如：”老王(XXX群)：你好啊！“
								pushContent = fromNickname + "(" + gname + "):" + parseMessageForShow(content, msgType);
							} else {
								log.debug("【向iOS离线推送群聊天消息】本次无需推送，原因：从"
										+ "缓存中没有查到发送者信息，即toGid=" + toGid + "(" + g + "), fromUid=" + fromUid
										+ "(" + u + ")的缓存！{chatType=" + chatType + ",msgType=" + msgType + ",content="
										+ content + ",fromUid" + fromUid + ",toUid=" + toUid + ",toGid=" + toGid + "}");
								return;
							}
						}
					} else {
						log.debug("【向iOS离线推送群聊天消息】本次无需推送，原因：从"
								+ "缓存中没有查到群组息，即toGid=" + toGid + "(" + g + "), fromUid=" + fromUid
								+ "的缓存！{chatType=" + chatType + ",msgType=" + msgType + ",content="
								+ content + ",fromUid" + fromUid + ",toUid=" + toUid + ",toGid=" + toGid + "}");
						return;
					}
				}
				// 如果是一对一聊天（陌生人聊天、好友聊天）
				else {
					UserInfo4Cache u = usersInfoCacheProvider.get(fromUid);
					if (u != null) {
						String fromNickname = u.getNickName();

						// 形如：”老王：你好啊！“
						pushContent = fromNickname + ":" + parseMessageForShow(content, msgType);
					} else {
						log.debug("【向iOS离线推送一对一聊天消息】本次无需推送，原因：从"
								+ "缓存中没有查到相关缓存，fromUid=" + fromUid
								+ "(" + u + ")的缓存！{chatType=" + chatType + ",msgType=" + msgType + ",content="
								+ content + ",fromUid" + fromUid + ",toUid=" + toUid + ",toGid=" + toGid + "}");
						return;
					}
				}

				if (pushContent != null) {
					// -1表示清除未读。自20240408起为了提升体验，将此值由-1改为了1，日后如果总离线消息数可以通过高速缓存得到，则此值取未读数就对了
					Http2APNSPusher.getInstance().push(iosTokenInfo.getIosDeviceToken(), null, pushContent, 1);
				} else {
					log.debug("【向iOS离线推送聊天消息】本次无需推送，原因：pushContent=null！"
							+ " {chatType=" + chatType + ",msgType=" + msgType + ",content="
							+ content + ",fromUid" + fromUid + ",toUid=" + toUid + ",toGid=" + toGid + "}");
				}
			} else {
				log.debug("【向iOS离线推送聊天消息】本次无需推送，原因：无该用户" + toUid + "的ios设备token数据。"
						+ " {chatType=" + chatType + ",msgType=" + msgType + ",content="
						+ content + ",fromUid" + fromUid + ",toUid=" + toUid + ",toGid=" + toGid + "}");
			}
		} catch (Exception e) {
			log.warn("【向iOS离线推送聊天消息】推送失败，原因："
					+ e.getMessage() + " {chatType=" + chatType + ",msgType=" + msgType + ",content="
					+ content + ",fromUid" + fromUid + ",toUid=" + toUid + ",toGid=" + toGid + "}", e);
		}
	}

	/**
	 * 尝试向加好友被请求者发送ios的离线推送送通知。
	 * 
	 * @param toUid   被请求者
	 * @param fromUid 好友请求发起者
	 */
	public void tryPushAddFriendProcess_request(String toUid, String fromUid) {
		UserInfo4Cache u = usersInfoCacheProvider.get(fromUid);
		if (u != null) {
			String fromNickname = u.getNickName();
			_tryPushAddFriendProcess(toUid, fromNickname + " 请求加你为好友", "【向iOS离线推送-请求加好友】");
		} else {
			log.debug("【向iOS离线推送-请求加好友】 本次无需推送，原因：从"
					+ "缓存中没有查到相关缓存，fromUid=" + fromUid + "(" + u + ")的缓存！{toUid=" + toUid + "}");
			return;
		}
	}

	/**
	 * 尝试发出被加者拒绝加好请求的ios离线通知。
	 * 
	 * @param friendNickname 被加者的昵称
	 * @param srcUid         加友发起人（也就是本次要通知的对象）
	 */
	public void tryPushAddFriendProcess_reject(String friendNickname, String srcUid) {
		_tryPushAddFriendProcess(srcUid, friendNickname + " 拒绝了你的好友请求", "【向iOS离线推送-拒绝加好友】");
	}

	/**
	 * 尝试发出加好请求成功的ios离线通知（给请求发起者）。
	 * 
	 * @param srcUid         好友请求发起者（也就是本次要通知的对象）
	 * @param friendNickname 被加者的昵称
	 */
	public void tryPushAddFriendProcess_accept(String srcUid, String friendNickname) {
		_tryPushAddFriendProcess(srcUid, friendNickname + " 已同意你的好友请求", "【向iOS离线推送-同意加好友】");
	}

	/**
	 * 尝试向已保存iOS设备token信息的用户进行添加好友（包括：发出好友请求、同意请求、拒绝请求）
	 * 相关通知的APNs消息推送。
	 * <p>
	 * 如果缓存中不存在该用户的ios设备token信息，则不需要推送。
	 * 
	 * @param toUid   要被推送的用户
	 * @param content 推送内容
	 */
	private void _tryPushAddFriendProcess(String toUid, String content, String TAG) {
		try {
			if (toUid == null || content == null) {
				throw new IllegalArgumentException("无效的参数toUid=" + toUid + ", content=" + content + "!");
			}

			// ## 尝试向ios设备进行APNs离线消息推送
			UserInfo4Cache iosTokenInfo = usersInfoCacheProvider.get(toUid);
			// 用户的Ios 设备token不为空才需要推送
			if (iosTokenInfo != null && !CommonUtils.isStringEmpty(iosTokenInfo.getIosDeviceToken())) {
				// -1表示清除未读。自20240408起为了提升体验，将此值由-1改为了1，日后如果总离线消息数可以通过高速缓存得到，则此值取未读数就对了
				Http2APNSPusher.getInstance().push(
						iosTokenInfo.getIosDeviceToken(), null, content, 1);
			} else {
				log.debug(TAG + " 本次无需推送，原因：无用户" + toUid + "的ios设备token数据。"
						+ " {uid=" + toUid + ",content=" + content + "}");
			}
		} catch (Exception e) {
			log.warn(TAG + " 推送失败，原因："
					+ e.getMessage() + " {uid=" + toUid + ",content=" + content + "}", e);
		}
	}

	/**
	 * 根据消息类型，显示友好的文字内容供某些情况下的预览（比如首页”消息“列表中、系统通知等）.
	 */
	private static String parseMessageForShow(String messageContent, int msgType) {
		if (messageContent == null)
			return "";

		String messageContentForShow = "";
		switch (msgType) {
			case MsgBodyRoot.TYPE_IMAGE:
				messageContentForShow = "[图片]";
				break;
			case MsgBodyRoot.TYPE_VOICE:
				messageContentForShow = "[语音]";
				break;
			case MsgBodyRoot.TYPE_GIFT$SEND:
				messageContentForShow = "[收到礼物]";
				break;
			case MsgBodyRoot.TYPE_GIFT$GET:
				messageContentForShow = "[能送我个礼物吗？]";
				break;
			case MsgBodyRoot.TYPE_FILE:
				messageContentForShow = "[文件]";
				break;
			case MsgBodyRoot.TYPE_SHORTVIDEO:
				messageContentForShow = "[短视频]";
				break;
			case MsgBodyRoot.TYPE_CONTACT:
				messageContentForShow = "[名片消息]";
				break;
			case MsgBodyRoot.TYPE_LOCATION:
				messageContentForShow = "[位置]";
				break;
			case MsgBodyRoot.TYPE_VOIP$RECORD:
				messageContentForShow = "[实时音视频]";
				break;
			case MsgBodyRoot.TYPE_REVOKE:
				messageContentForShow = "撤回了一条消息";
				break;
			default:
				messageContentForShow = messageContent;
				break;
		}

		return messageContentForShow;
	}

}
